﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections;
namespace DiamondDesktop.utility
{
    public class SAPISpeaker
    {


        object _spVoiceCls = null;	 //保存朗读用的 SAPI.SpVoice 
        const int SpFlags = 1; //SpeechVoiceSpeakFlags.SVSFlagsAsyn
        object _oISpeechObjectTokens = null; //保存 SAPI.ISpeechObjectTokens 就是系统有的语音引擎集合
        int TokensCount = 0; // 语音引擎集合数
        DictionaryEntry[] _deTokens = null; //榜定下拉框用的

        public SAPISpeaker()
        {
            InitSAPI();
        }

        #region 调用com组件，功能通用函数
        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name"></param>
        /// <param name="o"></param>
        /// <param name="vlaue"></param>
        private static void SetComProperty(string name, object o, object vlaue)
        {
            Type t = o.GetType();
            t.InvokeMember(name, BindingFlags.Instance | BindingFlags.SetProperty, null, o, new object[] { vlaue });
        }
        /// <summary>
        /// 取得属性
        /// </summary>
        /// <param name="name"></param>
        /// <param name="o"></param>
        /// <returns></returns>
        private static object GetComPropery(string name, object o)
        {
            Type t = o.GetType();
            return t.InvokeMember(name, BindingFlags.Instance | BindingFlags.GetProperty, null, o, null);
        }
        /// <summary>
        /// 调用方法函授
        /// </summary>
        /// <param name="name"></param>
        /// <param name="o"></param>
        /// <param name="parms"></param>
        /// <returns></returns>
        private static object CallComMethod(string name, object o, params object[] parms)
        {
            Type t = o.GetType();

            return t.InvokeMember(name, BindingFlags.Instance | BindingFlags.InvokeMethod, null, o, parms);
        }
        /// <summary>
        /// 创建 com 对象
        /// </summary>
        /// <param name="FromProgID"></param>
        /// <returns></returns>
        private static object CreateComObject(string FromProgID)
        {
            Type comType = Type.GetTypeFromProgID(FromProgID);
            object rVar = null;
            if (comType != null)
                rVar = System.Activator.CreateInstance(comType);

            return rVar;
        }
        #endregion


        public void Speak(string msg)
        {
            if (msg.Length != 0)
            {

                if (_spVoiceCls != null)
                {
                    //设置语言引擎
                    SetComProperty("Voice", _spVoiceCls, null);
                    //调用Speak 函数，msg 是要播放的文本，1 是异步播放,因为是异步的 com 对象不立刻释放
                    CallComMethod("Speak", _spVoiceCls, msg, SpFlags);

                }
            }

        }


        void InitSAPI()
        {
            //创建语音对象朗读用
            _spVoiceCls = CreateComObject("SAPI.SpVoice");

            if (_spVoiceCls == null)
            {
                return;
            }
            else
            {//取得所有的 识别对象模块集合


                _oISpeechObjectTokens = CallComMethod("GetVoices", _spVoiceCls); //取得 SAPI.ISpeechObjectTokens
                //识别对象集合 Count;
                object r = GetComPropery("Count", _oISpeechObjectTokens);
                if (r is int)
                {

                    TokensCount = (int)r;

                    if (TokensCount > 0)
                    {
                        //取得全部语音识别对象模块，及名称，以被以后使用
                        _deTokens = new DictionaryEntry[TokensCount];
                        for (int i = 0; i < TokensCount; i++)
                        {
                            //从集合中取出单个 识别对象模块
                            object oSpObjectToken = CallComMethod("Item", _oISpeechObjectTokens, i); //返回 SAPI.SpObjectToken
                            //取名称
                            string Description = CallComMethod("GetDescription", oSpObjectToken) as string;
                            //放到 DictionaryEntry 对象中，key 是 识别对象模块，value 是名称
                            _deTokens[i] = new DictionaryEntry(oSpObjectToken, Description);

                        }

                    }

                }

            }

        }


    }
}
